package com.example.playlet.utils;

import net.sf.json.JSONObject;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.HashMap;
import java.util.Map;

public class BatisUtil {
    public static void main(String[] args) {

    }

    /**
     * 字符替换
     *
     * @param beReplaced  待替换字符的字符串
     * @param replaceFrom 需要被替换的字符或字符串
     * @param replaceTo   替换后的字符或字符串
     * @return 替换后的字符串
     * <p>
     * 此方法使用正则表达式进行字符串替换，因此replaceFrom参数需要是一个有效的正则表达式
     * 如果replaceFrom中的字符需要进行转义，应确保正确转义，否则可能导致匹配失败或错误的替换结果
     */
    public static String places(String beReplaced, String replaceFrom, String replaceTo) {
        return beReplaced.replaceAll(replaceFrom, replaceTo);
    }

    /**
     * 特殊字符替换
     * 此方法用于替换XML字符串中的特殊字符，以避免XML解析错误或XSS攻击等安全问题
     * 它移除了或替换了包括HTML/XML实体、标点符号和空白字符在内的特殊字符
     *
     * @param xmlValue 待处理的XML字符串
     * @return 替换后的字符串，如果输入为空则返回null
     */
    public static String escape4XML(String xmlValue) {
        if (isEmptys(xmlValue) == true) {
            return null;
        } else {
            // 以下代码行替换了XML/HTML中的特殊实体，以防止解析错误和XSS攻击
            xmlValue = places(xmlValue, "&", "");
            xmlValue = places(xmlValue, "<", "");
            xmlValue = places(xmlValue, ">", "");
            xmlValue = places(xmlValue, "'", "");
            xmlValue = places(xmlValue, "\"", "");

            // 进一步替换可能引起解析问题的预定义实体
            xmlValue = places(xmlValue, "&amp;", "");
            xmlValue = places(xmlValue, "&lt;", "");
            xmlValue = places(xmlValue, "&gt;", "");
            xmlValue = places(xmlValue, "&apos;", "");
            xmlValue = places(xmlValue, "&quot;", "");

            // 替换中文标点符号，这些符号在XML中可能不是有效的字符
            xmlValue = places(xmlValue, "“", "");
            xmlValue = places(xmlValue, "”", "");
            xmlValue = places(xmlValue, "‘", "");
            xmlValue = places(xmlValue, "’", "");

            // 替换英文标点符号和多余的引号，以避免格式问题和潜在的安全风险
            xmlValue = places(xmlValue, "'", "");
            xmlValue = places(xmlValue, "\"\"", "");

            // 替换中文和英文的逗号、句号以及分号，以保持一致性并避免解析错误
            xmlValue = places(xmlValue, "，", "");
            xmlValue = places(xmlValue, "。", "");
            xmlValue = places(xmlValue, ",", "");
            xmlValue = places(xmlValue, "\\.", "");
            xmlValue = places(xmlValue, "\\;", "");
            xmlValue = places(xmlValue, "；", "");

            // 替换反斜杠和正斜杠，这些字符在某些上下文中可能会引起问题
            xmlValue = places(xmlValue, "\\\\", " ");
            xmlValue = places(xmlValue, "/", " ");

            // 移除换行符和制表符，以清理输入并防止潜在的格式问题
            xmlValue = places(xmlValue, "\\r|\n", "");

            // 注释掉的代码行可以用于更严格的清理，包括所有空白字符的替换
            // xmlValue = places(xmlValue, "\\s*|\r|\n|\t", "");
            // 返回清理后的字符串，去除前后空白字符
            return xmlValue.trim();
        }
    }

    /**
     * 将半角字符转换为全角字符
     * 此方法遍历输入字符串中的每个字符，如果字符是半角空格，则将其转换为全角空格（Unicode值为\u3000）；
     * 如果字符是其他半角字符（ASCII值小于127），则将其转换为对应的全角字符通过加上偏移量65248实现
     * 这样做是因为全角字符的Unicode值比半角字符的ASCII值大65248
     *
     * @param input 待转换的字符串
     * @return 转换后的全角字符串
     */
    public static String ToSBC(String input) {
        char c[] = input.toCharArray();
        for (int i = 0; i < c.length; i++) {
            if (c[i] == ' ') {
                c[i] = '\u3000';
            } else if (c[i] < '\177') {
                c[i] = (char) (c[i] + 65248);
            }
        }
        return new String(c);
    }

    /**
     * 将全角字符转换为半角字符
     * 全角字符通常用于中文文本输入，而半角字符是标准的ASCII字符
     * 这个方法主要用于将字符串中的全角字符转换为相应的半角字符，以便在计算机系统中进行统一处理
     *
     * @param input 待转换的字符串，其中可能包含全角字符
     * @return 转换后的字符串，其中的全角字符被替换为相应的半角字符
     */
    public static String ToDBC(String input) {
        // 将输入字符串转换为字符数组，以便逐个字符处理
        char c[] = input.toCharArray();
        for (int i = 0; i < c.length; i++) {
            // 检查字符是否是全角空格，并将其替换为半角空格
            if (c[i] == '\u3000') {
                c[i] = ' ';
            } else if (c[i] > '\uFF00' && c[i] < '\uFF5F') {
                // 检查字符是否在全角字符范围内，如果是，则将其转换为相应的半角字符
                c[i] = (char) (c[i] - 65248);
            }
        }
        // 将处理后的字符数组转换回字符串
        String returnString = new String(c);
        // 返回转换后的字符串
        return returnString;
    }

    /**
     * 判断给定的字符串是否为空
     * 如果字符串为空，则返回"0"，否则返回原字符串
     * 此方法主要用于简化字符串空判断的处理逻辑
     *
     * @param str 待判断的字符串
     * @return 字符串为空时返回"0"，否则返回原字符串
     */
    public static String emptys(String str) {
        if (isEmptys(str) == true) {
            return "0";
        } else {
            return str;
        }
    }
    /**
     * 正则表达式替换字符串中的中英文标点符号特殊字符
     */
    /**
     * 正则表达式替换字符串中的中英文标点符号特殊字符
     * 此方法用于移除字符串中的所有中英文标点符号和特殊字符，保留字母和数字
     * 主要用途是数据预处理，去除可能影响文本处理的噪声字符
     *
     * @param str 待处理的字符串
     * @return 移除标点符号和特殊字符后的字符串如果输入为空，则返回空字符串
     */
    public static String replaces(String str) {
        // 检查输入字符串是否为空或无效
        if (isEmptys(str) == false) {
            // 使用正则表达式移除所有中英文标点符号和特殊字符
            // \pP 匹配所有标点符号
            // \p{Punct} 匹配所有 ASCII 标点符号
            return escape(str.replaceAll("[\\pP\\p{Punct}]", ""));
        } else {
            // 如果输入为空，则直接返回空字符串
            return "";
        }
    }

    /**
     * 标点符号替换(,;，；)
     * 本函数旨在将字符串中的特定标点符号替换为空格或其他字符
     * 主要处理的标点符号包括：逗号(,), 分号(;), 中文逗号（，）和中文分号（；）
     *
     * @param str 待处理的字符串
     * @return 替换标点符号后的字符串
     */
    public static String escape(String str) {
        // 检查字符串是否为空或仅包含空格
        if (isEmptys(str) == false) {
            // 以下代码块用于替换不同标点符号
            if (str.contains(",") == true) {
                // 替换英文逗号为单个空格
                return escape(str.replaceAll(",", " ").trim()).trim();

            } else if (str.contains("，") == true) {
                // 替换中文逗号为单个空格
                return escape(str.replaceAll("，", " ").trim()).trim();

            } else if (str.contains(";") == true) {
                // 替换英文分号为单个空格
                return escape(str.replaceAll(";", " ").trim()).trim();

            } else if (str.contains("；") == true) {
                // 替换中文分号为单个空格
                return escape(str.replaceAll("；", " ").trim()).trim();
            } else {
                // 如果不包含指定标点符号，仅去除字符串两端的空格后返回
                return str.trim();
            }
        } else {
            // 如果字符串为空或仅包含空格，则直接返回空字符串
            return "";
        }
    }

    /**
     * 判断字符串是否为空
     *
     * @param str 字符串
     * @return true:为空;false:不为空
     */
    public static boolean isEmptys(String str) {
        if (str == null || str.length() == 0) {
            // 为空
            return true;
        } else {
            // 不为空
            return false;
        }
    }

    /**
     * 创建一个带有前缀的格式化数字字符串
     * 此方法用于生成一个数字字符串，该字符串前面补有固定数量的零，以满足指定的格式长度
     * 如果提供了前缀，方法将确保生成的字符串包括前缀在内，达到指定的格式长度；
     * 如果没有提供前缀，生成的字符串将直接符合格式长度
     *
     * @param prefix 前缀字符串，表示数字字符串之前的固定字符序列，如果不需要前缀则可以为空
     * @param format 格式长度，表示最终生成的数字字符串的总长度，包括前缀和数字部分
     * @return 返回一个格式化的数字字符串，前面补有适当数量的零，以满足指定的格式长度
     */
    public static String createNumber(String prefix, Integer format) {
        String rule = "";
        // 判断前缀是否为空
        if (isEmptys(prefix) == false) {
            // 如果前缀不为空，计算需要补零的长度，并生成相应的格式化规则
            rule = "%0" + (format - prefix.length()) + "d";
        } else {
            // 如果前缀为空，直接使用指定的格式长度生成格式化规则
            rule = "%0" + format + "d";
        }
        // 返回生成的格式化规则
        return rule;
    }

    /**
     * 生成JSON对象字符串
     * 该方法用于创建一个包含结果和消息的JSON对象字符串，主要用于数据封装和传输
     *
     * @param result  操作结果，通常用于表示操作的成功或失败
     * @param message 操作消息，用于描述操作的结果详情
     * @return 返回包含结果和消息的JSON对象字符串
     */
    public static String getJSONObject(String result, String message) {
        // 创建一个HashMap用于存储结果和消息键值对
        Map map = new HashMap();
        // 将结果和消息放入Map中
        map.put("code", result);
        map.put("message", message);
        // 使用JSONObject工具类将Map转换为JSON对象
        JSONObject jsosn = JSONObject.fromObject(map);
        // 返回JSON对象的字符串表示
        return jsosn.toString();
    }

    /**
     * 生成Json对象
     * 此方法用于创建一个包含结果信息的JSON对象，主要用于简化JSON对象的创建过程
     * 它将结果信息、消息和路径封装到一个JSON对象中
     *
     * @param result  操作结果，通常用于表示操作的成功或失败
     * @param message 操作消息，提供更详细的说明或错误信息
     * @param path    操作路径，可能用于指示操作的相关资源路径
     * @return 返回一个包含上述信息的JSONObject对象
     */
    public static JSONObject getJSONObject(String result, String message, String path) {
        // 创建一个HashMap用于存储JSON对象的数据
        Map map = new HashMap();
        // 将结果信息放入Map中
        map.put("code", result);
        // 将消息信息放入Map中
        map.put("message", message);
        // 将Map转换为JSONObject对象
        JSONObject jsosn = JSONObject.fromObject(map);
        // 返回JSONObject对象
        return jsosn;
    }


    /**
     * @param num 待格式化的数字对象，如果传入null，则默认返回"0"
     * @return 格式化后的字符串表示的数字
     * @Description 格式化数字，根据数字大小返回适当格式的字符串
     * <p>此方法旨在提供一种直观的方式来显示大数字，通过使用"万"、"亿"、"兆"和"京"单位</p>
     * @Author 张衡
     * @Email zhloveway@yeah.net
     * @Date: 2025-05-28 10:08:27
     * @Version 1.0
     */
    public static String formatNumber(Number num) {
        // 检查输入是否为null，如果是，则返回"0"
        if (num == null) return "0";
        // 将输入转换为double类型以便于后续处理
        double value = num.doubleValue();
        // 根据数字的大小选择合适的格式化方式
        if (value < 10000) {
            // 对于小于10000的数字，直接格式化为整数显示
            return String.valueOf((int) value);
        } else if (value < 100000000) {
            // 对于小于1亿的数字，以"万"为单位进行格式化，保留1位小数
            double truncated = BigDecimal.valueOf(value / 10000).setScale(1, RoundingMode.DOWN).doubleValue();
            return String.format("%.1f万", truncated);
        } else if (value < 1000000000000L) {
            // 对于小于1万亿（兆）的数字，以"亿"为单位进行格式化，保留2位小数
            double truncated = BigDecimal.valueOf(value / 100000000).setScale(2, RoundingMode.DOWN).doubleValue();
            return String.format("%.2f亿", truncated);
        } else if (value < 100000000000000L) {
            // 对于小于100万亿的数字，以"兆"为单位进行格式化，保留3位小数
            double truncated = BigDecimal.valueOf(value / 1000000000000L).setScale(3, RoundingMode.DOWN).doubleValue();
            return String.format("%.3f兆", truncated);
        } else {
            // 对于大于等于100万亿的数字，以"京"为单位进行格式化，保留4位小数
            double truncated = BigDecimal.valueOf(value / 100000000000000L).setScale(4, RoundingMode.DOWN).doubleValue();
            return String.format("%.4f京", truncated);
        }
    }

}
